package com.ys.utils.aspects;

import com.ys.base.EnumType;
import com.ys.utils.annotation.GroupValidateAnnotation;
import com.ys.utils.base.j2se.StringHandler;
import com.ys.utils.help.GroupUtils;
import com.ys.utils.help.UserUtils;
import com.ys.utils.redis.Redis;
import com.ys.utils.redis.key.GroupKey;
import com.ys.utils.spring.config.SystemError;
import com.ys.web.user.friends.mapper.UserGroupMapper;
import com.ys.web.user.friends.po.BaseGroupInfoPO;
import com.ys.web.user.friends.vo.UserGroupVO;
import com.ys.web.user.login.LoginInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ 名称:
 * @ 创建人: dhf
 * @ 参数： null
 * @ 创建时间: 2022/5/10
 * @ 修改人和其它信息
 * @ 返回值:
 */
@Slf4j
@Aspect
@Component
public class GroupValidateAspect {

    @Autowired
    private UserGroupMapper userGroupMapper;

    @Pointcut("@annotation(com.ys.utils.annotation.GroupValidateAnnotation)")
    public void groupPointCut() {
    }

    @Around("groupPointCut() && @annotation(anno)")
    public Object proceed(ProceedingJoinPoint thisJoinPoint, GroupValidateAnnotation anno) throws Throwable {
        //获取到请求参数
        Map<String, Object> fieldsName = getFieldsName(thisJoinPoint);
        Object uid = fieldsName.get("uid");
        Object groupId = fieldsName.get("groupId");
        Object unValidate = fieldsName.get("unValidate");
        if (StringHandler.isEmpty(uid) || StringHandler.isEmpty(groupId)) {
            SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "参数传递错误");
        }

        //判断用户是不是已经被禁用
        LoginInfo cacheUser = UserUtils.getCacheUser(uid);
        if (StringHandler.isNotEmpty(cacheUser)) {
            UserUtils.validateUserAccountStatus(StringHandler.getString(uid));
        } else {
            SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "用户信息异常.");
        }

        //是否需要进行验证获取数据
        if (StringHandler.isNotEmpty(unValidate)) {
            return thisJoinPoint.proceed(thisJoinPoint.getArgs());
        }

        //判断群的基础信息状态
        BaseGroupInfoPO cacheGroupInfo = GroupUtils.getCacheGroupInfo(String.valueOf(groupId));
        if (cacheGroupInfo != null && cacheGroupInfo.getStatus()) {
            //判断群是否被封
            if (StringHandler.isNotEmpty(cacheGroupInfo.getIsFreeze()) && cacheGroupInfo.getIsFreeze()) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "该群聊已被封禁");
            }
        }

        //验证操作人是否在群里面
        Boolean flag = GroupUtils.isInGroup(String.valueOf(groupId), String.valueOf(uid));
        if (flag) {
            return thisJoinPoint.proceed(thisJoinPoint.getArgs());
        } else {
            String key = GroupKey.groupMembersKey(groupId);
            if (Redis.zSet.range(key, 0, -1).size() == 0) {
                //如果状态存在  重新构建群的成员信息
                if (cacheGroupInfo != null && cacheGroupInfo.getStatus()) {
                    if (cacheGroupInfo.getIsFreeze() != null && cacheGroupInfo.getIsFreeze()) {
                        SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "该群聊已被封禁");
                    }

                    List<UserGroupVO> members = userGroupMapper.getCurrentGroupMembersAll(groupId);
                    Set<ZSetOperations.TypedTuple<String>> tuples = new HashSet<>();
                    members.stream().forEach(obj -> {
                        DefaultTypedTuple<String> defaultTypedTuple = new DefaultTypedTuple<>(obj.getUserId(), obj.getUserIdentity().doubleValue());
                        if(StringHandler.isNotEmpty(obj.userId)||StringHandler.getLong(obj.userId)>0 ) {
                            tuples.add(defaultTypedTuple);
                        }
                    });
                    Redis.zSet.add(key, tuples);

                    List<String> collect = members.stream().map(UserGroupVO::getUserId).collect(Collectors.toList());
                    if (collect.contains(String.valueOf(uid))) {
                        return thisJoinPoint.proceed(thisJoinPoint.getArgs());
                    }
                }
            }
        }
        SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "您当前不在群组中，操作失败");
        return null;
    }

    private static Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
        // 参数值
        Object[] args = joinPoint.getArgs();
        DefaultParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String[] parameterNames = pnd.getParameterNames(method);
        Map<String, Object> paramMap = new HashMap<>(32);
        for (int i = 0; i < parameterNames.length; i++) {
            paramMap.put(parameterNames[i], args[i]);
        }
        return paramMap;
    }
}
